/*
 * @Author: bor_fish 1219854025@qq.com
 * @Date: 2025-04-22 15:23:10
 * @LastEditors: bor_fish 1219854025@qq.com
 * @LastEditTime: 2025-05-26 15:57:27
 * @FilePath: /myCAN/Diagnostic_thread.h
 */

#pragma once
#include "Listener.h"
#include <array>
#include <mutex>
#include <thread>
#include <atomic>
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstring>
#include <chrono>

#include <string>
#include <vector>
#include <cstdint>


enum class DiagnosticErrorType {
    None,
    InvalidFrameId,
    InvalidDLC,
    CRCError,
    FeedbackTimeout,
    // 可扩展更多类型
};

struct DiagnosticError {
    uint32_t frame_id;                // 出错的CAN ID
    DiagnosticErrorType type;         // 错误类型
    std::string description;          // 错误描述
    int64_t timestamp_ns = 0;         // 可选：出错时间戳
};
class DiagnosticThread
{
protected:
    // 父类中指向 正在工作的线程
    std::thread worker_;
    // 正在工作线程索引
    int thread_Index_;

    // 几路CAN设备，目前三路
    static constexpr size_t kCanSize = 3;
    // 每路CAN设备存储数据缓冲区大小，同一路CAN可以存放6000个数据包
    static constexpr size_t kResultBufferSize = 6000;
    // 每个数据包大小
    static constexpr size_t kResultFrameSize = 10;

    // 用于存储上一个数据包的时间戳
    int64_t last_timestamp = 0;
    // 用于标记是否是第一个数据包
    bool first_packet = true;

    CanListener& listener_;

    // 执行时间统计相关变量-Debug
    double total_execution_time = 0.0;
    int execution_count = 0;
    double avg_execution_time = 0.0;
    double execution_time = 0.0;

public:

    // 构造函数，初始化列表
    DiagnosticThread(int index, CanListener& listener) 
        : thread_Index_(index), listener_(listener) {}
    // 析构函数
    virtual ~DiagnosticThread()
    {
        if (worker_.joinable())
        {
            worker_.join();
        }
    }
    // 纯虚函数
    virtual void parseData() = 0;
    // 启动线程
    void start()
    {
        worker_ = std::thread(&DiagnosticThread::parseData, this);
    }

    // 获取线程运行状态
    static bool isRunning() {
        return CanListener::isRunning();
    }
    // 打印时间戳的通用函数
    static void printTimestamp(const unsigned char* packet) {
        // 从packet中提取时间戳
        int64_t timestamp;
        std::memcpy(&timestamp, &packet[2], sizeof(int64_t));
        
        // 将纳秒转换为秒和纳秒部分
        auto seconds = timestamp / 1000000000;
        auto nanoseconds = timestamp % 1000000000;
        
        // 转换为时间结构
        std::time_t time_seconds = seconds;
        std::tm* timeinfo = std::localtime(&time_seconds);
        
        // 格式化输出
        // std::cout << "TimeStamp: " << std::put_time(timeinfo, "%Y-%m-%d %H:%M:%S") << "."
        //          << std::setfill('0') << std::setw(3) << nanoseconds << std::endl;
    }

        // 计算并输出时间间隔的通用函数
    static int64_t calculateTimeInterval(const unsigned char* current_packet, int64_t& last_timestamp, bool& first_packet) {
        // 从当前数据包中提取时间戳
        int64_t current_timestamp;
        std::memcpy(&current_timestamp, &current_packet[2], sizeof(int64_t));
        int64_t time_diff = 0;
        // 计算并输出时间间隔（如果不是第一个数据包）
        if (!first_packet) {
            time_diff = (int64_t)((current_timestamp - last_timestamp)/ 1000.0);//us
        } else {
            first_packet = false;
        }
        
        // 更新上一个时间戳
        last_timestamp = current_timestamp;
        // std::cout << "Time Interval: " << std::fixed << std::setprecision(3) 
        // << time_diff << " us" << std::endl;
        return time_diff;
    }

    // 获取CanListener的引用
    CanListener& getListener() { return listener_; }
};
